package com.rdtravel.valueobjects;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Transient;
import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.hibernate.validator.constraints.CreditCardNumber;

@Embeddable
public class CreditCard implements Serializable {
	private static final long serialVersionUID = 1L;
	@Column(name = "creditcardid")
	@NotNull
	@Pattern(regexp="^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$",
			message="{invalidCreditCardId}")
	@CreditCardNumber(message="{invalidCreditCardId}")		
	private String id;
	@Transient
	@Min(1)
	@Max(12)
	private Integer expirationMonth;
	@Transient
	@Min(0)
	private Integer expirationYear;

	@AssertFalse(message = "{creditCardExpired}")
	public boolean isExpired() {
		if (expirationMonth == null || expirationYear == null) {
			return true;
		}
		Calendar calendar = Calendar.getInstance();
		Date today = calendar.getTime();
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.MONTH, expirationMonth - 1);
		calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) / 100 * 100 + expirationYear);
		return today.compareTo(calendar.getTime()) >=  0;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public Integer getExpirationMonth() {
		return expirationMonth;
	}

	public void setExpirationMonth(Integer expirationMonth) {
		this.expirationMonth = expirationMonth;
	}

	public Integer getExpirationYear() {
		return expirationYear;
	}

	public void setExpirationYear(Integer expirationYear) {
		this.expirationYear = expirationYear;
	}

	@Override
	public String toString() {
		return "CreditCard [id=" + id + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof CreditCard)) {
			return false;
		}
		CreditCard other = (CreditCard) obj;
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		return true;
	}

	public static String[] getExpirationMonthNumbers() {
		return new String[] { "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12" };
	}

	public static String[] getExpirationYearNumbers() {
		String[] expirationYearNumbers = new String[10];
		int year = Calendar.getInstance().get(Calendar.YEAR);
		for (int i = 0; i != expirationYearNumbers.length; i++) {
			String yearNumber = "0" + String.valueOf(year % 100);
			if (yearNumber.length() == 3) {
				yearNumber = yearNumber.substring(1);
			}
			expirationYearNumbers[i] = yearNumber;
			year++;
		}
		return expirationYearNumbers;
	}

}
